package br.com.farmabid.produto;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;


import br.com.farmabid.cadastro.ProdutosFarmacia;
import br.com.farmabid.persistence.AbstractDAO;

@Named("produtoDAO")
public class ProdutoDAO extends AbstractDAO {

	/**
	 * 
	 */
	private static final long serialVersionUID = 8913212293290517465L;

	public ProdutoDAO(EntityManager manager) {
		this.manager = manager;
	}
	
	public ProdutoDAO(){}
	
	public List<FormaApresentacao> recuperaProdutos(Integer pagina, Integer quantidadeRegistros){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		cq.select(tb);
		return (List<FormaApresentacao>) recuperaLista(montaQueryPaginada(cq, pagina, quantidadeRegistros));
	}
	
	public List<CategoriaProduto> recuperaCategoriasFilho(){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<CategoriaProduto> cq = qb.createQuery(CategoriaProduto.class);
		Root<CategoriaProduto> tb = cq.from(CategoriaProduto.class);
		cq.select(tb);
		Predicate n1 = qb.isNull(tb.get("categoriaPai"));
		cq.where(n1);
		return (List<CategoriaProduto>) recuperaLista(montaQuery(cq));
	}
	
	public FormaApresentacao recuperaFormaApresentacaoPorAnvisaMsEan(FormaApresentacao forma){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("anvisa"), forma.getAnvisa()), qb.equal(tb.get("ean"), forma.getEan()), qb.equal(tb.get("codigoms"), forma.getCodigoms()));
		return (FormaApresentacao) recuperaRegistro(montaQuery(cq));
	}
	
	public FormaApresentacao recuperaFormaApresentacaoPorAnvisa(String anvisa){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("anvisa"), anvisa));
		return (FormaApresentacao) recuperaRegistro(montaQuery(cq));
	}
	
	public FormaApresentacao recuperaFormaApresentacaoPorCodigoMs(String codigoms){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("codigoms"), codigoms));
		return (FormaApresentacao) recuperaRegistro(montaQuery(cq));
	}
	
	public FormaApresentacao recuperaFormaApresentacaoPorEan(String ean){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("ean"), ean));
		return (FormaApresentacao) recuperaRegistro(montaQuery(cq));
	}
	
	public List<Produto> recuperaProdutosPorNomeLike(String query) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<Produto> cq = qb.createQuery(Produto.class);
		Root<Produto> tb = cq.from(Produto.class);
		Expression<String> path = tb.get("nome");
		Predicate l1 = qb.like(path, "%" + query + "%");
		cq.select(tb);
		cq.where(l1);
		return (List<Produto>) recuperaLista(montaQuery(cq));
	}
	
	public List<ProdutoEstatistica> recuperaProdutosMaisBuscados(Integer quantidadeRegistros){
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<ProdutoEstatistica> cq = qb.createQuery(ProdutoEstatistica.class);
		Root<ProdutoEstatistica> tb = cq.from(ProdutoEstatistica.class);
		cq.select(tb);
		cq.orderBy(qb.desc(tb.get("quantidadeBuscado")));
		return (List<ProdutoEstatistica>) recuperaLista(montaQueryPaginada(cq, 1, quantidadeRegistros));
	}
	
	public List<ProdutoVO> recuperaProdutosDestaque(Integer quantidadeRegistros) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<ProdutosFarmacia> cq = qb.createQuery(ProdutosFarmacia.class);
		Root<ProdutosFarmacia> tb = cq.from(ProdutosFarmacia.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("ofertar"), 1));
		List<ProdutosFarmacia> listaProdutosFarmacia = (List<ProdutosFarmacia>) recuperaLista(montaQueryPaginada(cq, 1, quantidadeRegistros));
		
		List<ProdutoVO> listaProdutosVO = new ArrayList<ProdutoVO>();
		
		for(ProdutosFarmacia pf : listaProdutosFarmacia){
			FormaApresentacao fab = manager.find(FormaApresentacao.class, pf.getFormaApresentacao().getId());
			listaProdutosVO.add(converteFAparaProdutoVO(fab));
		}
		
		return listaProdutosVO;
	}
	
	public List<ProdutoVO> converteProdutoParaProdutoVO(Produto produto){
		List<ProdutoVO> listaProdutosVO = new ArrayList<ProdutoVO>();
		if(null != produto.getFormas() && produto.getFormas().size() > 0){
			for(FormaApresentacao fa : produto.getFormas()){
				ProdutoVO pd = new ProdutoVO();
				pd.setAnvisa(fa.getAnvisa());
				pd.setApresentacao(fa.getApresentacao().getNome());
				pd.setAtivo(produto.getAtivo());
				pd.setCategoria(fa.getCategoria().getNome());
				pd.setConcentracao(fa.getConcentracao());
				pd.setFabricante(produto.getFabricante().getNome());
				pd.setFormaUso(fa.getFormaUso().getNome());
				pd.setId(produto.getId());
				pd.setIdForma(fa.getId());
				pd.setQuantidade(fa.getQuantidade());
				pd.setNome(produto.getNome());
				pd.setTipo(produto.getTipo().getNome());
				pd.setUnidade(fa.getUnidade().getNome());
				fa.getImagens();
				if(null != fa.getImagens() && fa.getImagens().size() > 0){
					List<String> listaIdsImagens = new ArrayList<String>();
					for(ProdutoImagem pi : fa.getImagens()){
						listaIdsImagens.add(pi.getId() + "");
					}
					pd.setImagens(listaIdsImagens);
				}
				if(null != produto.getIndicacoes() && produto.getIndicacoes().size() > 0){
					List<String> listaIndicacoes = new ArrayList<String>();
					for(Indicacao ind : produto.getIndicacoes()){
						listaIndicacoes.add(ind.getNome());
					}
					pd.setIndicacoes(listaIndicacoes);
				}
				if(null != produto.getPrincipios() && produto.getPrincipios().size() > 0){
					List<String> listaPrincipios = new ArrayList<String>();
					for(PrincipioAtivo ind : produto.getPrincipios()){
						listaPrincipios.add(ind.getNome());
					}
					pd.setPrincipios(listaPrincipios);
				}
				listaProdutosVO.add(pd);
			}
		}
		return listaProdutosVO;
	}
	
	public ProdutoVO converteFAparaProdutoVO(FormaApresentacao fa){
		ProdutoVO pd = new ProdutoVO();
		
		if(null != fa){
			pd.setAnvisa(fa.getAnvisa());
			pd.setApresentacao(fa.getApresentacao().getNome());
			pd.setAtivo(fa.getProduto().getAtivo());
			pd.setCategoria(fa.getCategoria().getNome());
			pd.setConcentracao(fa.getConcentracao());
			pd.setFabricante(fa.getProduto().getFabricante().getNome());
			pd.setFormaUso(fa.getFormaUso().getNome());
			pd.setId(fa.getProduto().getId());
			pd.setIdForma(fa.getId());
			pd.setQuantidade(fa.getQuantidade());
			pd.setNome(fa.getProduto().getNome());
			pd.setTipo(fa.getProduto().getTipo().getNome());
			pd.setUnidade(fa.getUnidade().getNome());
			fa.getImagens();
			if(null != fa.getImagens() && fa.getImagens().size() > 0){
				List<String> listaIdsImagens = new ArrayList<String>();
				for(ProdutoImagem pi : fa.getImagens()){
					listaIdsImagens.add(pi.getId() + "");
				}
				pd.setImagens(listaIdsImagens);
			}
				if(null != fa.getProduto().getIndicacoes() && fa.getProduto().getIndicacoes().size() > 0){
					List<String> listaIndicacoes = new ArrayList<String>();
					for(Indicacao ind : fa.getProduto().getIndicacoes()){
						listaIndicacoes.add(ind.getNome());
					}
					pd.setIndicacoes(listaIndicacoes);
				}
				if(null != fa.getProduto().getPrincipios() && fa.getProduto().getPrincipios().size() > 0){
					List<String> listaPrincipios = new ArrayList<String>();
					for(PrincipioAtivo ind : fa.getProduto().getPrincipios()){
						listaPrincipios.add(ind.getNome());
					}
					pd.setPrincipios(listaPrincipios);
				}
		}
		return pd;
	}

	public List<Indicacao> recuperaIndicacaoPorNomeLike(String nome) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<Indicacao> cq = qb.createQuery(Indicacao.class);
		Root<Indicacao> tb = cq.from(Indicacao.class);
		Expression<String> path = tb.get("nome");
		Predicate l1 = qb.like(path, "%" + nome + "%");
		cq.select(tb);
		cq.where(l1);
		return (List<Indicacao>) recuperaLista(montaQuery(cq));
	}

	public List<PrincipioAtivo> recuperaPrincipioPorNomeLike(String nome) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<PrincipioAtivo> cq = qb.createQuery(PrincipioAtivo.class);
		Root<PrincipioAtivo> tb = cq.from(PrincipioAtivo.class);
		Expression<String> path = tb.get("nome");
		Predicate l1 = qb.like(path, "%" + nome + "%");
		cq.select(tb);
		cq.where(l1);
		return (List<PrincipioAtivo>) recuperaLista(montaQuery(cq));
	}

	public Produto recuperaProdutoPorNomeFabricante(Produto produto) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<Produto> cq = qb.createQuery(Produto.class);
		Root<Produto> tb = cq.from(Produto.class);
		cq.select(tb);
		Fabricante fab = manager.find(Fabricante.class, produto.getFabricante().getId());
		cq.where(qb.equal(tb.get("nome"), produto.getNome()), qb.equal(tb.get("fabricante"), fab));
		Query query = manager.createQuery(cq);
		return (Produto) recuperaRegistro(query);
	}

	public ProdutosFarmacia recuperaProdutoFarmaciaPorIdFA(Integer id) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<ProdutosFarmacia> cq = qb.createQuery(ProdutosFarmacia.class);
		Root<ProdutosFarmacia> tb = cq.from(ProdutosFarmacia.class);
		cq.select(tb);
		FormaApresentacao fab = manager.find(FormaApresentacao.class, id);
		cq.where(qb.equal(tb.get("formaApresentacao"), fab));
		Query query = manager.createQuery(cq);
		return (ProdutosFarmacia) recuperaRegistro(query);
	}

	public Produto recuperaProdutoPorNome(String nome) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<Produto> cq = qb.createQuery(Produto.class);
		Root<Produto> tb = cq.from(Produto.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("nome"), nome));
		Query query = manager.createQuery(cq);
		return (Produto) recuperaRegistro(query);
	}

	public ProdutoEstatistica recuperaEstatisticasProduto(Produto produto) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<ProdutoEstatistica> cq = qb.createQuery(ProdutoEstatistica.class);
		Root<ProdutoEstatistica> tb = cq.from(ProdutoEstatistica.class);
		cq.select(tb);
		cq.where(qb.equal(tb.get("produto"), produto));
		Query query = manager.createQuery(cq);
		return (ProdutoEstatistica) recuperaRegistro(query);
	}

	public List<FormaApresentacao> recuperaFormaApresentacaoPorAnvisaLike(
			FormaApresentacao formaApresentacao) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		Expression<String> path = tb.get("anvisa");
		Predicate l1 = qb.like(path, "%" + formaApresentacao.getAnvisa() + "%");
		cq.select(tb);
		cq.where(l1);
		return (List<FormaApresentacao>) recuperaLista(montaQuery(cq));
	}

	public List<FormaApresentacao> recuperaFormaApresentacaoPorEanLike(
			FormaApresentacao formaApresentacao) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		Expression<String> path = tb.get("ean");
		Predicate l1 = qb.like(path, "%" + formaApresentacao.getEan() + "%");
		cq.select(tb);
		cq.where(l1);
		return (List<FormaApresentacao>) recuperaLista(montaQuery(cq));
	}

	public List<FormaApresentacao> recuperaFormaApresentacaoPorMsLike(
			FormaApresentacao formaApresentacao) {
		CriteriaBuilder qb = manager.getCriteriaBuilder();
		CriteriaQuery<FormaApresentacao> cq = qb.createQuery(FormaApresentacao.class);
		Root<FormaApresentacao> tb = cq.from(FormaApresentacao.class);
		Expression<String> path = tb.get("codigoms");
		Predicate l1 = qb.like(path, "%" + formaApresentacao.getCodigoms() + "%");
		cq.select(tb);
		cq.where(l1);
		return (List<FormaApresentacao>) recuperaLista(montaQuery(cq));
	}
	
}